package deepbrain.simnetwork.factory;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.Scanner;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import deepbrain.simnetwork.exception.SimNetworkException;
import deepbrain.simnetwork.network.NetworkState;
import deepbrain.simnetwork.network.NodeState;

public class XmlNetworkStateFactory implements NetworkStateFactory {

	private Document nodesXML;

	public XmlNetworkStateFactory(String filePath) throws SimNetworkException {
		try {
			InputStream inputStream = new FileInputStream(filePath);
			loadDocument(inputStream);
		} catch (FileNotFoundException e) {
			throw new SimNetworkException("Cannot Open File: " + filePath
					+ " When Loading Node States", e);
		}
	}

	public XmlNetworkStateFactory(InputStream inputStream)
			throws SimNetworkException {
		loadDocument(inputStream);
	}

	private void loadDocument(InputStream inputStream)
			throws SimNetworkException {
		SAXReader reader = new SAXReader();
		try {
			nodesXML = reader.read(inputStream);
		} catch (DocumentException e) {
			throw new SimNetworkException(
					"Cannot Parse Nodes XML When Loading Initial Node States",
					e);
		}
	}

	public NetworkState newNetworkState(int numOfNodes)
			throws SimNetworkException {

		if (nodesXML == null)
			return null;

		Element nodesElement = (Element) nodesXML
				.selectSingleNode("//network/nodes");
		/*
		 * String nodeStateType = nodesElement.elementTextTrim("state-type");
		 * 
		 * if (nodeStateType==null || nodeStateType.length()==0)
		 * 
		 * 
		 * Class nodeStateClass; try { nodeStateClass = (Class)
		 * Class.forName(nodeStateType); } catch (ClassNotFoundException e) {
		 * throw new SimNetworkException("Cannot Find Node State Class Type:" +
		 * nodeStateType + " When Loading Initial Node States", e); }
		 */
		int NumOfNodes = Integer.parseInt(nodesElement.elementTextTrim("num"));
		NodeState[] nodeStates = new NodeState[NumOfNodes];

		String nodeStatesString = nodesElement.elementTextTrim("states");
		Scanner scanner = new Scanner(nodeStatesString);
		String string;
		int p = 0;
		while (scanner.hasNext()) {
			string = scanner.next();
			NodeState state = NodeState.getStateFromString(string);
			nodeStates[p++] = state;
			if (p >= NumOfNodes)
				break;
		}

		return new NetworkState(nodeStates);
	}

}
